<template>
<div>
    <canvas id="canvas" :height="height" :width="width"></canvas>
</div>
</template>

<script>
export default {
    name: "CanvasDial",
    data() {
        return {
            width: 400,
            height: 400,
            convas: null, // canvas对象
            ctx: null, // canvas绘图环境
            contourRadius: 150, // 时钟半径
            scale: 60, // 刻度数
            hourList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], // 时针刻度列表
        };
    },
    mounted() {
        this.init();
    },
    destroy() {
       clearInterval(this.timer)
    },
    methods: {
        /**
         * 初始化
         */
        init() {
            // 获得canvas对象
            this.convas = document.getElementById("canvas");
            // 初始化canvas的绘图环境
            this.ctx = this.convas.getContext("2d");
            // this.ctx.translate(this.width / 2, this.height / 2); // 将绘图原点移到画布中心
            this.drawClock();
            // 每秒运行一次
            this.timer = setInterval(() => {
              this.drawClock();
            },1000)
        },
        /**
         * 运行
         */
        run(){
            // 获取时分秒
            const date = new Date();
            const hour = date.getHours();
            const minute = date.getMinutes();
            const second = date.getSeconds();
            // 绘制秒针
            this.drawSecond(second);
            // 绘制分针
            this.drawMinute(minute,second);
            // 绘制时针
            this.drawHour(hour,minute,second);
            // 绘制中心点
            this.drawCenter();
            this.ctx.restore(); // 恢复之前保存的绘图状态
        },
        /**
         * 绘制表
         */
        drawClock(){
            this.ctx.clearRect(0, 0, this.width, this.height); // 清除画布
            this.ctx.save();
            this.ctx.translate(this.width / 2, this.height / 2); // 将绘图原点移到画布中心
            this.drawCircle();// 绘制时钟轮廓
            this.drawScale();// 绘制刻度
            this.run();// 运行
            this.ctx.restore(); // 恢复之前保存的绘图状态
        },
        /**
         * 绘制时钟轮廓
         */
        drawCircle() {
            const x = 0;
            const y = 0;
            this.ctx.beginPath();
            this.ctx.lineWidth = 15; // 设置线宽
            this.ctx.arc(x, y, this.contourRadius, 0, 2 * Math.PI); // 绘制圆形
            this.ctx.strokeStyle = '#000000'; // 设置虚线颜色
            this.ctx.stroke(); // 描边
        },
        /**
         * 绘制刻度
         */
        drawScale() {
            // 绘制刻度
            for (let i = 0; i < this.scale; i++) {
                // 计算刻度的角度
                const angle = (2 * Math.PI / this.scale) * i;
                // 计算刻度的坐标
                const x =  Math.cos(angle) * this.contourRadius;
                const y =  Math.sin(angle) * this.contourRadius;
                if (i % 5 === 0) {
                    this.drawDots(x, y, '#ff0202', 5); // 绘制大刻度
                } else {
                    this.drawDots(x, y, '#999999', 3); // 绘制小刻度
                }
            }
            // 绘制数字
            for (let i = 0; i < this.hourList.length; i++) {
                // 计算数字的角度
                const angle = (2 * Math.PI / this.hourList.length) * i - 60 * Math.PI / 180;
                // 计算数字的坐标
                const x =  Math.cos(angle) * (this.contourRadius - 30);
                const y =  Math.sin(angle) * (this.contourRadius - 30);
                this.drawText(this.hourList[i], x, y, '#333'); // 绘制数字
            }
        },
        /**
         * 绘制中心点
         */
        drawCenter() {
            const x = 0;
            const y = 0;
            this.ctx.save(); // 保存当前绘图状态
            this.drawDots(x, y, '#fff', 5); // 绘制中心点
            this.ctx.restore(); // 恢复之前保存的绘图状态
        },
        /**
         * 绘制时针
         * @param h
         */
        drawHour(h, m, s)   {
            const rH = (2* Math.PI / 12) * h;
            const rM = ((2* Math.PI / 12) / 60) * m;
            const rS = ((2* Math.PI / 12) / 60 / 60) * s;
            const rotate = rH + rM + rS;
            const x1 = 0;
            const y1 =  this.contourRadius * 0.5 *0.2;
            const x2 = 0;
            const y2 =  - this.contourRadius * 0.5 *0.8;
            this.drawLine(x1, y1, x2, y2, rotate, '#333333');


        },
        /**
         * 绘制分针
         * @param m
         */
        drawMinute(m,s) {
            const rM = (2* Math.PI / 60) * m;
            const rS = ((2* Math.PI / 60) / 60) * s;
            const rotate = rM + rS;
            const x1 = 0;
            const y1 =  this.contourRadius * 0.8 *0.2;
            const x2 = 0;
            const y2 =  - this.contourRadius * 0.8 *0.8;
            this.drawLine(x1, y1, x2, y2, rotate, '#333333');
        },
        /**
         * 绘制秒针
         * @param s
         */
        drawSecond(s) {
            // 计算秒针的角度
            const rotate = (2* Math.PI / 60) * s;
            const x1 = 0;
            const y1 =  this.contourRadius * 0.9 *0.2;
            const x2 = 0;
            const y2 =  - this.contourRadius * 0.9 *0.8;
            this.drawLine(x1, y1, x2, y2, rotate, '#ff0000');
        },
        /**
         * 绘制圆点
         */
        drawDots(x, y, color, radius) {
            this.ctx.beginPath();
            this.ctx.fillStyle = color;
            this.ctx.arc(x, y, radius, 0, 2 * Math.PI);
            this.ctx.fill(); // 填充
        },
        /**
         * 绘制文字
         */
        drawText(text, x, y, color, fontSize = '16px', fontFamily = '微软雅黑') {
            this.ctx.textAlign = 'center';
            this.ctx.textBaseline = 'middle';
            this.ctx.font = fontSize + ' ' + fontFamily;
            this.ctx.fillStyle = color;
            this.ctx.beginPath();
            this.ctx.fillText(text, x, y);
            this.ctx.fill();
        },
        /**
         *
         * @param x1
         * @param y1
         * @param x2
         * @param y2
         * @param rotate
         * @param color
         * @param lineWidth 线条宽度
         * @param lineCap 线条末端样式 butt round square
         */
        drawLine(x1, y1, x2, y2,rotate, color,lineWidth = 8,lineCap = 'round')  {
            this.ctx.save(); // 保存当前绘图状态
            this.ctx.beginPath();
            this.ctx.rotate(rotate); // 旋转
            this.ctx.strokeStyle = color;
            this.ctx.lineWidth = lineWidth; // 设置线条宽度
            this.ctx.lineCap = lineCap; // 设置线条末端样式
            this.ctx.moveTo(x1, y1); // 移动到起点
            this.ctx.lineTo(x2, y2); // 绘制直线
            this.ctx.stroke(); // 描边
            this.ctx.restore(); // 恢复之前保存的绘图状态
        }
    }
}
</script>

<style scoped>

</style>
